home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Pascal string, C string, and formatting utility routines
- **
- ** This module contains routines for
- **
- ** + Copying, concatenating, and comparing Macintosh
- ** pascal-style (leading byte contains length) strings
- **
- ** + Converting Macintosh pascal-style strings to/from C-style
- ** (NUL terminated) strings
- **
- ** + Formatting numbers as pascal-style strings
- **
- ** + Performing substitutions on pascal-style strings (formatting)
- **
- ** Best of all, they're free!
- **
- ** Written by Alan B. Mimms, 22 Oct, 1987
- **
- ** Permission is hereby granted to freely duplicate, modify, disseminate,
- ** and otherwise distribute this software until your heart's content.
- ** No copyright is claimed. However, I am not responsible for the
- ** performance of this software and may not be held accountable for
- ** any failure of the software to perform in any way under any circum-
- ** stances.
- */
-
- #include "Pstr.h"
-
- /*
- ** Uncomment the following line and link with stdio and MacTraps
- ** (LightspeedC, anyway) to run the test stuff for numfmt ()...
- **
- ** #define DEBUGMAIN
- */
-
-
- /*
- ** Compare two pascal strings, returning a zero if they're equal,
- ** a negative number if s1 is less than s2, or
- ** a positive number if s1 is greater than s2.
- */
-
- int pstrcmp (s1, s2)
-
- register uchar *s1, *s2;
-
- {
- register int i;
- register int c;
- int len = *s1 < *s2 ? *s1 : *s2;
-
- for (i = 1; i <= len; ++i)
- if (c = s1 [i] - s2 [i]) return (c);
-
- if (*s1 == *s2)
- return (0);
- else if (*s1 < *s2)
- return (-1);
- else
- return (1);
- }
-
-
- /*
- ** Copy pascal string "s2" into the buffer to which "s1" points.
- ** NOTE: It is assumed that the buffer (s1) is large enough for
- ** the entire string "s2". Returns "s1".
- */
- uchar *pstrcpy (s1, s2)
-
- register uchar *s1, *s2;
-
- {
- register int i;
-
- for (i = 0; i <= *s2; ++i) s1 [i] = s2 [i];
- return (s1);
- }
-
-
- /*
- ** Concatenate the pascal string "s2" onto the end of the current
- ** contents of the pascal string "s1". Returns "s1".
- */
- uchar *pstrcat (s1, s2)
-
- register uchar *s1, *s2;
-
- {
- register int i;
-
- for (i = 1; i <= s2 [0]; ++i)
- s1 [++s1 [0]] = s2 [i];
-
- return (s1);
- }
-
-
- /*
- ** Copy C-style (NUL terminated) string "c" to buffer to which "p"
- ** points as a pascal-style (leading byte contains length) string.
- ** Returns "p".
- */
- uchar *cpyc2p (p, c)
-
- register uchar *p, *c;
-
- {
- for (*p = 0; *c; ++c, ++*p)
- p [*p] = *c;
-
- return (p);
- }
-
-
- /*
- ** Copy pascal-style string "p" into buffer to which "c" points as a
- ** C-style string. Returns "c".
- */
- uchar *cpyp2c (c, p)
-
- register uchar *c, *p;
-
- {
- register int len;
- uchar *oldc;
-
- for (oldc = c, len = *p++; len; --len)
- *c++ = *p++;
-
- *c = 0;
- return (oldc);
- }
-
-
- /*
- ** Format the number "n" in specified "radix" (2..16) using "width" as the
- ** desired field width. If "width" is greater than zero, leading
- ** blanks will be inserted to fill the result string to "width"
- ** bytes in length. If "width" is less than zero, the leading zeroes
- ** will be inserted instead of leading blanks. If "width" is zero,
- ** the minimum field width necessary to represent the value (i.e.,
- ** with no leading zeroes or leading blanks) will be used. If "radix"
- ** is zero, the default radix 10 will be used. Places the formatted
- ** number into the buffer to which "string" points (at least 34 bytes
- ** should be allocated for it -- you can use typedef "numbuf") as a
- ** pascal-style string. Returns "string".
- */
- unsigned char *numfmt (string, n, width, radix)
-
- register uchar *string;
- register long n;
- int width, radix;
-
- {
- register int w;
- int wasneg, realwidth = width;
- long realN = n;
- static char digits [] = "0123456789ABCDEF";
-
- if (!radix) radix = 10;
- if (!width) width = 33;
- string [0] = w = width < 0 ? -width : width;
-
- if (wasneg = (n < 0)) {
- n = -n;
- wasneg = (width > 0);
- }
-
- for ( ; w; --w) {
- uchar c = digits [n % radix];
-
- if (!n && c == '0')
- if (wasneg) {
- c = '-';
- wasneg = 0;
- } else if (w != string [0] && width > 0) c = ' ';
-
- string [w] = c;
- n /= radix;
- }
-
- if (!realwidth) {
- register int i, j;
-
- for (i = 1; i < string [0]; ++i)
- if (string [i] != ' ') break;
-
- for (j = 1; i <= string [0]; ++i, ++j)
- string [j] = string [i];
-
- string [0] = j - 1;
- } else if (n || wasneg)
- for (w = 1; w <= string [0]; ++w)
- string [w] = '*';
- else if (realwidth < 0 && realN < 0)
- string [1] = '-';
-
- return (string);
- }
-
-
- /*
- ** Substitutes within the pascal-style string "result" the leftmost
- ** occurrence of the substring (pascal-style) "target" with the new
- ** substring (again, pascal-style) "source", and returns "result".
- */
- uchar *mungpstr (result, target, source)
-
- uchar *result, *target, *source;
-
- {
- register int r, delta;
-
- /* Find position of target in result */
-
- for (r = 1; r <= result [0] - target [0] + 1; ++r)
- {
- register int t;
-
- for (t = 1; t <= target [0]; ++t)
-
- if (target [t] != result [r + t - 1])
- goto NotThisTime;
-
- goto FoundTarget;
-
- NotThisTime: ;
- }
-
- return (result); /* No target string found in result */
-
- FoundTarget:
- delta = source [0] - target [0];
-
- if (delta > 0)
- {
- register int k;
-
- for (k = result [0]; k >= r; --k)
- result [k + delta] = result [k];
- }
- else if (delta < 0)
- {
- register int k;
-
- for (k = r + source [0]; k <= result [0]; ++k)
- result [k] = result [k - delta];
- }
-
- result [0] += delta;
-
- for (delta = 1; delta <= source [0]; ++delta)
- result [r++] = source [delta];
-
- return (result);
- }
-
-
- /*
- ** Calls "mungpstr" repeatedly on the pascal-style string "msg"
- ** with successive pairs of parameters for the "target" and "source"
- ** strings. Calling sequence (in reality) is like this:
- **
- ** Str255 buf;
- ** numbuf nbuf [34];
- **
- ** mungmsg (
- ** pstrcpy (buf, "\PReplace foo with bar and X with a hex number"),
- ** "\Pfoo", "\Pbar",
- ** "\PX", numfmt (nbuf, 12345678L, 0, 16),
- ** (uchar *) 0);
- **
- ** This call results in the string
- **
- ** "Replace bar with bar and BC614E with a hex number"
- */
- uchar *mungmsg (msg, mungitems)
-
- uchar *msg, *mungitems;
-
- {
- register uchar **p;
-
- for (p = &mungitems; *p; p += 2) mungpstr (msg, p [0], p [1]);
- return (msg);
- }
-
-
- /*
- ** This is used during debugging...
- */
- #ifdef DEBUGMAIN
- #include <stdio.h>
-
- /* Put out a pascal-style string to stdout */
- static void putps (p)
-
- char *p;
-
- {
- int i;
-
- for (i = 1; i <= p [0]; ++i)
- putchar (p [i]);
-
- putchar ('\n');
- }
-
- #define TEST(v,w) numfmt(s,(v),(w),10);printf("%ld@%d=",(long)(v),(w));putps(s);
-
- main ()
-
- {
- uchar s [256];
-
- /* Test for faulty leading zero suppression */
- TEST (-3000789L, -12);
- TEST (-3000789L, 12);
- TEST (-3000789L, 0);
- TEST (3000789L, -12);
- TEST (3000789L, 12);
- TEST (3000789L, 0);
-
- /* Test for correct display */
- TEST (-123456789L, -12);
- TEST (-123456789L, 12);
- TEST (-123456789L, 0);
- TEST (123456789L, -12);
- TEST (123456789L, 12);
- TEST (123456789L, 0);
- TEST (0L, -12);
- TEST (0L, 12);
- TEST (0L, 0);
- }
- #endif DEBUGMAIN
-